/*
 * ECARX Technology Limited is the owner of the copyright and the trade secret of this software.
 * Without permission, no one has the right to obtain, disclose or use this software in any way.
 */

package com.ecarx.systemui.plugin.controller.hvac

import android.car.VehicleAreaSeat
import android.car.VehicleAreaType
import android.car.VehicleUnit
import android.car.hardware.property.CarPropertyManager.CarPropertyEventCallback
import com.ecarx.systemui.plugin.model.hvac.HvacPowerOnImpl
import com.ecarx.systemui.plugin.model.hvac.HvacTempImpl
import com.ecarx.systemui.plugin.model.hvac.HvacTempSyncImpl
import com.ecarx.systemui.plugin.model.hvac.HvacTempUnitImpl

class HvacTempController private constructor() {

    private val mTempSyncArea =
        VehicleAreaSeat.SEAT_ROW_1_LEFT or VehicleAreaSeat.SEAT_ROW_1_RIGHT or
                VehicleAreaSeat.SEAT_ROW_2_LEFT or VehicleAreaSeat.SEAT_ROW_2_RIGHT or
                VehicleAreaSeat.SEAT_ROW_2_CENTER

    private val mPowerOnArea =
        VehicleAreaSeat.SEAT_ROW_1_LEFT or VehicleAreaSeat.SEAT_ROW_1_RIGHT or
                VehicleAreaSeat.SEAT_ROW_2_LEFT or VehicleAreaSeat.SEAT_ROW_2_RIGHT or
                VehicleAreaSeat.SEAT_ROW_2_CENTER

    private val mTempUnitArea = VehicleAreaType.VEHICLE_AREA_TYPE_GLOBAL

    private val _defaultTemp = 22.0f

    private val tempIml = HvacTempImpl()
    private val tempSyncImpl = HvacTempSyncImpl()
    private val powerOnImpl = HvacPowerOnImpl()
    private val tempUnitImpl = HvacTempUnitImpl()

    suspend fun isPowerOn(): Boolean {
        if (!powerOnImpl.isAvailable(mPowerOnArea)) {
            return false
        }
        return powerOnImpl.getValue(mPowerOnArea)
    }

    suspend fun setPowerOn(isPowerOn: Boolean) {
        if (!powerOnImpl.isAvailable(mPowerOnArea)) {
            return
        }
        powerOnImpl.setValue(isPowerOn, mPowerOnArea)
    }

    suspend fun registerPowerOnCallback(callback: CarPropertyEventCallback) {
        if (!powerOnImpl.isAvailable(mPowerOnArea)) {
            return
        }
        powerOnImpl.registerCallback(callback)
    }

    suspend fun unRegisterPowerOnCallback(callback: CarPropertyEventCallback) {
        if (!powerOnImpl.isAvailable(mPowerOnArea)) {
            return
        }
        powerOnImpl.unRegisterCallback(callback)
    }

    suspend fun getCurrentTemp(area: Int): Float {
        if (!tempIml.isAvailable(area)) {
            return _defaultTemp
        }
        return tempIml.getValue(area)
    }

    suspend fun setTemp(temp: Float, area: Int) {
        if (!tempIml.isAvailable(area)) {
            return
        }
        tempIml.setValue(temp, area)
    }

    suspend fun registerTempCallback(callback: CarPropertyEventCallback) {
        tempIml.registerCallback(callback)
    }

    suspend fun unRegisterTempCallback(callback: CarPropertyEventCallback) {
        tempIml.unRegisterCallback(callback)
    }

    suspend fun isTempUnitAvailable(): Boolean {
        return tempUnitImpl.isAvailable(mTempUnitArea)
    }

    suspend fun getTempUnit(): Int {
        if (!isTempUnitAvailable()) {
            return VehicleUnit.CELSIUS
        }
        return tempUnitImpl.getValue(mTempUnitArea)
    }

    suspend fun isTempSyncAvailable(): Boolean {
        return tempSyncImpl.isAvailable(mTempSyncArea)
    }

    suspend fun isTempSync(): Boolean {
        if (!isTempSyncAvailable()) {
            return false
        }
        return tempSyncImpl.getValue(mTempSyncArea)
    }

    suspend fun setTempSync(isSync: Boolean) {
        if (!isTempSyncAvailable()) {
            return
        }
        tempSyncImpl.setValue(isSync, mTempSyncArea)
    }

    suspend fun registerTempSyncCallback(callback: CarPropertyEventCallback) {
        if (!isTempSyncAvailable()) {
            return
        }
        tempSyncImpl.registerCallback(callback)
    }

    suspend fun unRegisterTempSyncCallback(callback: CarPropertyEventCallback) {
        if (!isTempSyncAvailable()) {
            return
        }
        tempSyncImpl.unRegisterCallback(callback)
    }

    suspend fun registerTempUnitCallback(callback: CarPropertyEventCallback) {
        if (!isTempUnitAvailable()) {
            return
        }
        tempUnitImpl.registerCallback(callback)
    }

    suspend fun unRegisterTempUnitCallback(callback: CarPropertyEventCallback) {
        if (!isTempUnitAvailable()) {
            return
        }
        tempUnitImpl.unRegisterCallback(callback)
    }

    companion object {
        private const val TAG = "HvacTempController"

        fun getInstance() = Holder.instance

        const val MAX_TEMP_C = 28.5f
        const val MIN_TEMP_C = 15.5f

        const val MAX_TEMP_F = 85f
        const val MIN_TEMP_F = 59f
    }

    object Holder {
        val instance = HvacTempController()
    }
}